home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow / Common / mfcutil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  20.2 KB  |  708 lines

  1. //------------------------------------------------------------------------------
  2. // File: MFCUtil.cpp
  3. //
  4. // Desc: DirectShow sample code - Utility functions used by MFC applications.
  5. //
  6. // Copyright (c) 2000-2001 Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9.  
  10. #include "stdafx.h"
  11. #include <dshow.h>
  12. #include <atlbase.h>
  13. #include "mfcutil.h"
  14.  
  15.  
  16. HRESULT AddGraphFiltersToList (IGraphBuilder *pGB, CListBox& m_ListFilters) 
  17. {
  18.     HRESULT hr;
  19.     IEnumFilters *pEnum = NULL;
  20.     IBaseFilter *pFilter = NULL;
  21.     ULONG cFetched;
  22.  
  23.     // Clear filters list box
  24.     m_ListFilters.ResetContent();
  25.     
  26.     // Verify graph builder interface
  27.     if (!pGB)
  28.         return E_NOINTERFACE;
  29.  
  30.     // Get filter enumerator
  31.     hr = pGB->EnumFilters(&pEnum);
  32.     if (FAILED(hr))
  33.     {
  34.         m_ListFilters.AddString(TEXT("<ERROR>"));
  35.         return hr;
  36.     }
  37.  
  38.     // Enumerate all filters in the graph
  39.     while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
  40.     {
  41.         FILTER_INFO FilterInfo;
  42.         TCHAR szName[256];
  43.         
  44.         hr = pFilter->QueryFilterInfo(&FilterInfo);
  45.         if (FAILED(hr))
  46.         {
  47.             m_ListFilters.AddString(TEXT("<ERROR>"));
  48.         }
  49.         else
  50.         {
  51.             USES_CONVERSION;
  52.  
  53.             // Add the filter name to the filters listbox
  54.             lstrcpy(szName, W2T(FilterInfo.achName));
  55.             m_ListFilters.AddString(szName);
  56.  
  57.             // Must release filter graph reference
  58.             FilterInfo.pGraph->Release();
  59.         }       
  60.         pFilter->Release();
  61.     }
  62.     pEnum->Release();
  63.  
  64.     return hr;
  65. }
  66.  
  67.  
  68. //
  69. // The GraphBuilder interface provides a FindFilterByName() method,
  70. // which provides similar functionality to the method below.
  71. // This local method is provided for educational purposes.
  72. //
  73. IBaseFilter *FindFilterFromName(IGraphBuilder *pGB, LPTSTR szNameToFind)
  74. {
  75.     USES_CONVERSION;
  76.  
  77.     HRESULT hr;
  78.     IEnumFilters *pEnum = NULL;
  79.     IBaseFilter *pFilter = NULL;
  80.     ULONG cFetched;
  81.     BOOL bFound = FALSE;
  82.  
  83.     // Verify graph builder interface
  84.     if (!pGB)
  85.         return NULL;
  86.  
  87.     // Get filter enumerator
  88.     hr = pGB->EnumFilters(&pEnum);
  89.     if (FAILED(hr))
  90.         return NULL;
  91.  
  92.     // Enumerate all filters in the graph
  93.     while((pEnum->Next(1, &pFilter, &cFetched) == S_OK) && (!bFound))
  94.     {
  95.         FILTER_INFO FilterInfo;
  96.         TCHAR szName[256];
  97.         
  98.         hr = pFilter->QueryFilterInfo(&FilterInfo);
  99.         if (FAILED(hr))
  100.         {
  101.             pFilter->Release();
  102.             pEnum->Release();
  103.             return NULL;
  104.         }
  105.  
  106.         // Compare this filter's name with the one we want
  107.         lstrcpy(szName, W2T(FilterInfo.achName));
  108.         if (! lstrcmp(szName, szNameToFind))
  109.         {
  110.             bFound = TRUE;
  111.         }
  112.  
  113.         FilterInfo.pGraph->Release();
  114.  
  115.         // If we found the right filter, don't release its interface.
  116.         // The caller will use it and release it later.
  117.         if (!bFound)
  118.             pFilter->Release();
  119.         else
  120.             break;
  121.     }
  122.     pEnum->Release();
  123.  
  124.     return (bFound ? pFilter : NULL);
  125. }
  126.  
  127.  
  128. HRESULT EnumFiltersWithCLSIDToList(ICreateDevEnum *pSysDevEnum, 
  129.                                    const GUID *clsid, CListBox& List)
  130. {
  131.     HRESULT hr;
  132.     IEnumMoniker *pEnumCat = NULL;
  133.  
  134.     // Instantiate the system device enumerator if it doesn't exist
  135.     if (pSysDevEnum == NULL)
  136.     {
  137.         hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, 
  138.                               CLSCTX_INPROC, IID_ICreateDevEnum, 
  139.                               (void **)&pSysDevEnum);
  140.         if FAILED(hr)
  141.             return hr;
  142.     }
  143.  
  144.     // Enumerate all filters of the selected category  
  145.     hr = pSysDevEnum->CreateClassEnumerator(*clsid, &pEnumCat, 0);
  146.     if (SUCCEEDED(hr))
  147.     {
  148.         // Enumerate all filters using the category enumerator
  149.         hr = EnumFiltersAndCLSIDsToList(pEnumCat, List);
  150.  
  151.         SAFE_RELEASE(pEnumCat);
  152.     }
  153.  
  154.     pSysDevEnum->Release();
  155.     return hr;
  156. }
  157.  
  158.  
  159. HRESULT EnumFiltersWithMonikerToList(ICreateDevEnum *pSysDevEnum, 
  160.                                      const GUID *clsid, CListBox& List)
  161. {
  162.     HRESULT hr;
  163.     IEnumMoniker *pEnumCat = NULL;
  164.  
  165.     // Instantiate the system device enumerator if it doesn't exist
  166.     if (pSysDevEnum == NULL)
  167.     {
  168.         hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, 
  169.                               CLSCTX_INPROC, IID_ICreateDevEnum, 
  170.                               (void **)&pSysDevEnum);
  171.         if FAILED(hr)
  172.             return hr;
  173.     }
  174.  
  175.     // Enumerate all filters of the selected category  
  176.     hr = pSysDevEnum->CreateClassEnumerator(*clsid, &pEnumCat, 0);
  177.     if (SUCCEEDED(hr))
  178.     {
  179.         // Enumerate all filters using the category enumerator
  180.         hr = EnumFiltersAndMonikersToList(pEnumCat, List);
  181.  
  182.         SAFE_RELEASE(pEnumCat);
  183.     }
  184.  
  185.     pSysDevEnum->Release();
  186.     return hr;
  187. }
  188.  
  189.  
  190. HRESULT EnumFiltersAndMonikersToList(IEnumMoniker *pEnumCat, CListBox& ListFilters)
  191. {
  192.     HRESULT hr=S_OK;
  193.     IMoniker *pMoniker;
  194.     ULONG cFetched;
  195.     VARIANT varName={0};
  196.     int nFilters=0;
  197.  
  198.     // If there are no filters of a requested type, show default string
  199.     if (!pEnumCat)
  200.     {
  201.         ListFilters.AddString(TEXT("<< No entries >>"));
  202.         return S_FALSE;
  203.     }
  204.  
  205.     // Enumerate all items associated with the moniker
  206.     while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
  207.     {
  208.         IPropertyBag *pPropBag;
  209.         ASSERT(pMoniker);
  210.  
  211.         // Associate moniker with a file
  212.         hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
  213.                                     (void **)&pPropBag);
  214.         ASSERT(SUCCEEDED(hr));
  215.         ASSERT(pPropBag);
  216.         if (FAILED(hr))
  217.             continue;
  218.  
  219.         // Read filter name from property bag
  220.         varName.vt = VT_BSTR;
  221.         hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  222.         if (FAILED(hr))
  223.             continue;
  224.  
  225.         // Get filter name (converting BSTR name to a CString)
  226.         CString str(varName.bstrVal);
  227.         SysFreeString(varName.bstrVal);
  228.         nFilters++;
  229.  
  230.         // Add the filter name and moniker to the listbox
  231.         AddFilterToListWithMoniker(str, pMoniker, ListFilters);
  232.        
  233.         // Cleanup interfaces
  234.         SAFE_RELEASE(pPropBag);
  235.  
  236.         // Intentionally DO NOT release the pMoniker, since it is
  237.         // stored in a listbox for later use
  238.     }
  239.  
  240.     return hr;
  241. }
  242.  
  243.  
  244. HRESULT EnumFiltersAndCLSIDsToList(IEnumMoniker *pEnumCat, CListBox& ListFilters)
  245. {
  246.     HRESULT hr=S_OK;
  247.     IMoniker *pMoniker;
  248.     ULONG cFetched;
  249.     VARIANT varName={0};
  250.     int nFilters=0;
  251.  
  252.     // If there are no filters of a requested type, show default string
  253.     if (!pEnumCat)
  254.     {
  255.         ListFilters.AddString(TEXT("<< No entries >>"));
  256.         return S_FALSE;
  257.     }
  258.  
  259.     // Enumerate all items associated with the moniker
  260.     while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
  261.     {
  262.         IPropertyBag *pPropBag;
  263.         ASSERT(pMoniker);
  264.  
  265.         // Associate moniker with a file
  266.         hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
  267.                                     (void **)&pPropBag);
  268.         ASSERT(SUCCEEDED(hr));
  269.         ASSERT(pPropBag);
  270.         if (FAILED(hr))
  271.             continue;
  272.  
  273.         // Read filter name from property bag
  274.         varName.vt = VT_BSTR;
  275.         hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  276.         if (FAILED(hr))
  277.             continue;
  278.  
  279.         // Get filter name (converting BSTR name to a CString)
  280.         CString str(varName.bstrVal);
  281.         SysFreeString(varName.bstrVal);
  282.         nFilters++;
  283.  
  284.         // Read filter's CLSID from property bag.  This CLSID string will be
  285.         // converted to a binary CLSID and passed to AddFilter(), which will
  286.         // add the filter's name to the listbox and its CLSID to the listbox
  287.         // item's DataPtr item.  When the user clicks on a filter name in
  288.         // the listbox, we'll read the stored CLSID, convert it to a string,
  289.         // and use it to find the filter's filename in the registry.
  290.         VARIANT varFilterClsid;
  291.         varFilterClsid.vt = VT_BSTR;
  292.  
  293.         // Read CLSID string from property bag
  294.         hr = pPropBag->Read(L"CLSID", &varFilterClsid, 0);
  295.         if(SUCCEEDED(hr))
  296.         {
  297.             CLSID clsidFilter;
  298.  
  299.             // Add filter name and CLSID to listbox
  300.             if(CLSIDFromString(varFilterClsid.bstrVal, &clsidFilter) == S_OK)
  301.             {
  302.                 AddFilterToListWithCLSID(str, &clsidFilter, ListFilters);
  303.             }
  304.  
  305.             SysFreeString(varFilterClsid.bstrVal);
  306.         }
  307.        
  308.         // Cleanup interfaces
  309.         SAFE_RELEASE(pPropBag);
  310.         SAFE_RELEASE(pMoniker);
  311.     }
  312.  
  313.     return hr;
  314. }
  315.  
  316.  
  317. HRESULT EnumPinsOnFilter (IBaseFilter *pFilter, PIN_DIRECTION PinDir,
  318.                           CListBox& Listbox)
  319. {
  320.     HRESULT hr;
  321.     IEnumPins  *pEnum = NULL;
  322.     IPin *pPin = NULL;
  323.  
  324.     // Clear the specified listbox (input or output)
  325.     Listbox.ResetContent();
  326.  
  327.     // Verify filter interface
  328.     if (!pFilter)
  329.         return E_NOINTERFACE;
  330.  
  331.     // Get pin enumerator
  332.     hr = pFilter->EnumPins(&pEnum);
  333.     if (FAILED(hr))
  334.     {
  335.         Listbox.AddString(TEXT("<ERROR>"));
  336.         return hr;
  337.     }
  338.  
  339.     pEnum->Reset();
  340.  
  341.     // Enumerate all pins on this filter
  342.     while((hr = pEnum->Next(1, &pPin, 0)) == S_OK)
  343.     {
  344.         PIN_DIRECTION PinDirThis;
  345.  
  346.         hr = pPin->QueryDirection(&PinDirThis);
  347.         if (FAILED(hr))
  348.         {
  349.             Listbox.AddString(TEXT("<ERROR>"));
  350.             pPin->Release();
  351.             continue;
  352.         }
  353.  
  354.         // Does the pin's direction match the requested direction?
  355.         if (PinDir == PinDirThis)
  356.         {
  357.             PIN_INFO pininfo={0};
  358.  
  359.             // Direction matches, so add pin name to listbox
  360.             hr = pPin->QueryPinInfo(&pininfo);
  361.             if (SUCCEEDED(hr))
  362.             {
  363.                 CString str(pininfo.achName);
  364.                 Listbox.AddString(str);
  365.                 //RetailOutput(_T("pPin=0x%x\n"), pPin);
  366.             }
  367.  
  368.             // The pininfo structure contains a reference to an IBaseFilter,
  369.             // so you must release its reference to prevent resource a leak.
  370.             pininfo.pFilter->Release();
  371.         }
  372.         pPin->Release();
  373.     }
  374.     pEnum->Release();
  375.  
  376.     return hr;
  377. }
  378.  
  379.  
  380. HRESULT AddFilterPinsToLists (IGraphBuilder *pGB, CListBox& m_ListFilters,
  381.                              CListBox& m_ListPinsInput, CListBox& m_ListPinsOutput) 
  382. {
  383.     HRESULT hr;
  384.     IBaseFilter *pFilter = NULL;
  385.     TCHAR szNameToFind[128];
  386.  
  387.     // Read the current filter name from the list box
  388.     int nCurSel = m_ListFilters.GetCurSel();
  389.     m_ListFilters.GetText(nCurSel, szNameToFind);
  390.  
  391.     // Read the current list box name and find it in the graph
  392.     pFilter = FindFilterFromName(pGB, szNameToFind);
  393.     if (!pFilter)
  394.         return E_UNEXPECTED;
  395.  
  396.     // Now that we have filter information, enumerate pins by direction
  397.     // and add their names to the appropriate listboxes
  398.     //RetailOutput(_T("Listing input pins on filter %s\n"), szNameToFind);
  399.     hr = EnumPinsOnFilter(pFilter, PINDIR_INPUT, m_ListPinsInput);
  400.  
  401.     if (SUCCEEDED(hr))
  402.     {
  403.         //RetailOutput(_T("Listing output pins on filter %s\n"), szNameToFind);
  404.         hr = EnumPinsOnFilter(pFilter, PINDIR_OUTPUT, m_ListPinsOutput);
  405.     }
  406.     
  407.     // Must release the filter interface returned from FindFilterByName()
  408.     pFilter->Release();
  409.  
  410.     return hr;
  411. }
  412.  
  413.  
  414. BOOL GetFileInfoStrings(LPTSTR szFile, TCHAR *szSize, TCHAR *szDate)
  415. {
  416.     HANDLE hFile;
  417.     LONGLONG llSize=0;
  418.     DWORD dwSizeLow=0, dwSizeHigh=0;
  419.  
  420.     // Open the specified file to read size and date information
  421.     hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, 
  422.                        OPEN_EXISTING, (DWORD) 0, NULL);
  423.  
  424.     if (hFile == INVALID_HANDLE_VALUE)
  425.     {
  426.         RetailOutput(TEXT("*** Failed(0x%x) to open file (to read size)!\r\n"),
  427.                      GetLastError());
  428.         return FALSE;
  429.     }
  430.  
  431.     if (szSize)
  432.     {
  433.         dwSizeLow = GetFileSize(hFile, &dwSizeHigh);
  434.         if ((dwSizeLow == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
  435.         {
  436.             RetailOutput(TEXT("*** Error(0x%x) reading file size!\r\n"),
  437.                          GetLastError());
  438.             CloseHandle(hFile);
  439.             return FALSE;
  440.         }
  441.  
  442.         // Large files will also use the upper DWORD to report size.
  443.         // Add them together for the true size if necessary.
  444.         if (dwSizeHigh)
  445.             llSize = (dwSizeHigh << 16) + dwSizeLow;
  446.         else
  447.             llSize = dwSizeLow;
  448.  
  449.         // Update size string
  450.         wsprintf(szSize, TEXT("Size: %d bytes\0"), dwSizeLow);
  451.     }
  452.  
  453.     if (szDate)
  454.     {
  455.         // Read date information
  456.         BY_HANDLE_FILE_INFORMATION fi;
  457.         if (GetFileInformationByHandle(hFile, &fi))
  458.         {
  459.             CTime time(fi.ftLastWriteTime);
  460.  
  461.             // Update date string
  462.             wsprintf(szDate, TEXT("File date: %02d/%02d/%d\0"), 
  463.                      time.GetMonth(), time.GetDay(), time.GetYear());
  464.         }
  465.     }
  466.  
  467.     CloseHandle(hFile);
  468.     return TRUE;
  469. }
  470.  
  471.  
  472. void AddEventToList(CListBox& ListEvents, long lEventCode)
  473. {
  474.     static TCHAR szMsg[256];
  475.     BOOL bMatch = TRUE;
  476.  
  477. #define HANDLE_EC(c)                              \
  478.     case c:                                       \
  479.         wsprintf(szMsg, TEXT("%s\0"), TEXT(#c));  \
  480.         break;
  481.  
  482.     switch (lEventCode)
  483.     {
  484.         HANDLE_EC(EC_ACTIVATE);
  485.         HANDLE_EC(EC_BUFFERING_DATA);
  486.         HANDLE_EC(EC_CLOCK_CHANGED);
  487.         HANDLE_EC(EC_COMPLETE);
  488.         HANDLE_EC(EC_DEVICE_LOST);
  489.         HANDLE_EC(EC_DISPLAY_CHANGED);
  490.         HANDLE_EC(EC_END_OF_SEGMENT);
  491.         HANDLE_EC(EC_ERROR_STILLPLAYING);
  492.         HANDLE_EC(EC_ERRORABORT);
  493.         HANDLE_EC(EC_EXTDEVICE_MODE_CHANGE);
  494.         HANDLE_EC(EC_FULLSCREEN_LOST);
  495.         HANDLE_EC(EC_GRAPH_CHANGED);
  496.         HANDLE_EC(EC_LENGTH_CHANGED);
  497.         HANDLE_EC(EC_NEED_RESTART);
  498.         HANDLE_EC(EC_NOTIFY_WINDOW);
  499.         HANDLE_EC(EC_OLE_EVENT);
  500.         HANDLE_EC(EC_OPENING_FILE);
  501.         HANDLE_EC(EC_PALETTE_CHANGED);
  502.         HANDLE_EC(EC_PAUSED);
  503.         HANDLE_EC(EC_QUALITY_CHANGE);
  504.         HANDLE_EC(EC_REPAINT);
  505.         HANDLE_EC(EC_SEGMENT_STARTED);
  506.         HANDLE_EC(EC_SHUTTING_DOWN);
  507.         HANDLE_EC(EC_SNDDEV_IN_ERROR);
  508.         HANDLE_EC(EC_SNDDEV_OUT_ERROR);
  509.         HANDLE_EC(EC_STARVATION);
  510.         HANDLE_EC(EC_STEP_COMPLETE);
  511.         HANDLE_EC(EC_STREAM_CONTROL_STARTED);
  512.         HANDLE_EC(EC_STREAM_CONTROL_STOPPED);
  513.         HANDLE_EC(EC_STREAM_ERROR_STILLPLAYING);
  514.         HANDLE_EC(EC_STREAM_ERROR_STOPPED);
  515.         HANDLE_EC(EC_TIMECODE_AVAILABLE);
  516.         HANDLE_EC(EC_USERABORT);
  517.         HANDLE_EC(EC_VIDEO_SIZE_CHANGED);
  518.         HANDLE_EC(EC_WINDOW_DESTROYED);
  519.  
  520.     default:
  521.         bMatch = FALSE;
  522.         RetailOutput(TEXT("  Received unknown event code (0x%x)\r\n"), lEventCode);
  523.         break;
  524.     }
  525.  
  526.     // If a recognized event was found, add its name to the events list box
  527.     if (bMatch)
  528.         ListEvents.AddString(szMsg);
  529. }
  530.  
  531.  
  532. void RetailOutput(TCHAR *tszErr, ...)
  533. {
  534.     TCHAR tszErrOut[MAX_PATH + 256];
  535.  
  536.     va_list valist;
  537.  
  538.     va_start(valist,tszErr);
  539.     wvsprintf(tszErrOut, tszErr, valist);
  540.     OutputDebugString(tszErrOut);
  541.     va_end (valist);
  542. }
  543.  
  544.  
  545. void AddFilterCategoriesToList(CListBox& ListFilters)
  546. {
  547.     HRESULT hr;
  548.     IEnumMoniker *pEmCat = 0;
  549.     ICreateDevEnum *pCreateDevEnum = NULL;
  550.     int nClasses=0;
  551.  
  552.     // Create an enumerator
  553.     hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
  554.                           IID_ICreateDevEnum, (void**)&pCreateDevEnum);
  555.     ASSERT(SUCCEEDED(hr));
  556.     if (FAILED(hr))
  557.         return;
  558.  
  559.     // Use the meta-category that contains a list of all categories.
  560.     // This emulates the behavior of GraphEdit.
  561.     hr = pCreateDevEnum->CreateClassEnumerator(
  562.                          CLSID_ActiveMovieCategories, &pEmCat, 0);
  563.     ASSERT(SUCCEEDED(hr));
  564.  
  565.     if(hr == S_OK)
  566.     {
  567.         IMoniker *pMCat;
  568.         ULONG cFetched;
  569.  
  570.         // Enumerate over every category
  571.         while(hr = pEmCat->Next(1, &pMCat, &cFetched),
  572.               hr == S_OK)
  573.         {
  574.             IPropertyBag *pPropBag;
  575.  
  576.             // Associate moniker with a file
  577.             hr = pMCat->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
  578.             if(SUCCEEDED(hr))
  579.             {
  580.                 VARIANT varCatClsid;
  581.                 varCatClsid.vt = VT_BSTR;
  582.  
  583.                 // Read CLSID string from property bag
  584.                 hr = pPropBag->Read(L"CLSID", &varCatClsid, 0);
  585.                 if(SUCCEEDED(hr))
  586.                 {
  587.                     CLSID clsidCat;
  588.  
  589.                     if(CLSIDFromString(varCatClsid.bstrVal, &clsidCat) == S_OK)
  590.                     {
  591.                         USES_CONVERSION;
  592.  
  593.                         // Use the guid if we can't get the name
  594.                         WCHAR *wszCatName;
  595.                         TCHAR szCatDesc[MAX_PATH];
  596.  
  597.                         VARIANT varCatName;
  598.                         varCatName.vt = VT_BSTR;
  599.  
  600.                         // Read filter name
  601.                         hr = pPropBag->Read(L"FriendlyName", &varCatName, 0);
  602.                         if(SUCCEEDED(hr))
  603.                             wszCatName = varCatName.bstrVal;
  604.                         else
  605.                             wszCatName = varCatClsid.bstrVal;
  606.  
  607.                         lstrcpy(szCatDesc, W2T(wszCatName));
  608.  
  609.                         if(SUCCEEDED(hr))
  610.                             SysFreeString(varCatName.bstrVal);
  611.  
  612.                         // Add category name and CLSID to list box
  613.                         AddFilterToListWithCLSID(szCatDesc, &clsidCat, ListFilters);
  614.                         nClasses++;
  615.                     }
  616.  
  617.                     SysFreeString(varCatClsid.bstrVal);
  618.                 }
  619.  
  620.                 pPropBag->Release();
  621.             }
  622.             else
  623.             {
  624.                 break;
  625.             }
  626.  
  627.             pMCat->Release();
  628.         } // for loop
  629.  
  630.         pEmCat->Release();
  631.     }
  632.  
  633.     pCreateDevEnum->Release();
  634. }
  635.  
  636.  
  637. void AddFilterToListWithCLSID(const TCHAR *szFilterName, const GUID *pCatGuid, CListBox& ListFilters)
  638. {
  639.     // Allocate a new CLSID, whose pointer will be stored in 
  640.     // the listbox.  When the listbox is cleared, these will be deleted.
  641.     CLSID *pclsid = new CLSID;
  642.  
  643.     // Add the category name and a pointer to its CLSID to the list box
  644.     int nSuccess  = ListFilters.AddString(szFilterName);
  645.     int nIndexNew = ListFilters.FindStringExact(-1, szFilterName);
  646.  
  647.     if (pclsid)
  648.     {
  649.         *pclsid = *pCatGuid;
  650.         nSuccess = ListFilters.SetItemDataPtr(nIndexNew, pclsid);
  651.     }
  652. }
  653.  
  654.  
  655. void ClearFilterListWithCLSID(CListBox& ListFilters)
  656. {
  657.     CLSID *pStoredId = NULL;
  658.     
  659.     int nCount = ListFilters.GetCount();
  660.  
  661.     // Delete any CLSID pointers that were stored in the listbox item data
  662.     for (int i=0; i < nCount; i++)
  663.     {
  664.         pStoredId = (CLSID *) ListFilters.GetItemDataPtr(i);
  665.         if (pStoredId != 0)
  666.         {
  667.             delete pStoredId;
  668.             pStoredId = NULL;
  669.         }
  670.     }
  671.  
  672.     // Clean up
  673.     ListFilters.ResetContent();
  674. }
  675.  
  676.  
  677. void AddFilterToListWithMoniker(const TCHAR *szFilterName, 
  678.                                 IMoniker *pMoniker, CListBox& ListFilters)
  679. {
  680.     // Add the category name and a pointer to its CLSID to the list box
  681.     int nSuccess  = ListFilters.AddString(szFilterName);
  682.     int nIndexNew = ListFilters.FindStringExact(-1, szFilterName);
  683.     nSuccess = ListFilters.SetItemDataPtr(nIndexNew, pMoniker);
  684. }
  685.  
  686.  
  687. void ClearFilterListWithMoniker(CListBox& ListFilters)
  688. {
  689.     IMoniker *pMoniker = NULL;
  690.     
  691.     int nCount = ListFilters.GetCount();
  692.  
  693.     // Delete any CLSID pointers that were stored in the listbox item data
  694.     for (int i=0; i < nCount; i++)
  695.     {
  696.         pMoniker = (IMoniker *) ListFilters.GetItemDataPtr(i);
  697.         if (pMoniker != 0)
  698.         {
  699.             pMoniker->Release();
  700.             pMoniker = NULL;
  701.         }
  702.     }
  703.  
  704.     // Clean up
  705.     ListFilters.ResetContent();
  706. }
  707.  
  708.